package converthelp

import (
	"bytes"
	"encoding/json"
	"github.com/axgle/mahonia"
	"strconv"
)

// StructToMap 如果对应字段为nil 则不同步到m 适应可变字段更新
func StructToMap(obj interface{}) (m map[string]interface{}, err error) {
	r, err := json.Marshal(obj)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(r, &m)
	if err != nil {
		return nil, err
	}
	for k, v := range m {
		if v == nil {
			delete(m, k)
		}
	}
	return
}

// MapToStruct 把map数据转到struct
/*
参数m：为输入的map数据
参数a：为输出的struct，a为指针，需要new
*/
func MapToStruct(m any, a any) error {
	j, err := json.Marshal(m)
	if err != nil {
		return err
	}
	err = json.Unmarshal(j, a)
	if err != nil {
		return err
	}
	return nil
}

// Utf8ArrToGBK utf-8 字符串数组转 gbk 数组
func Utf8ArrToGBK(arr []string) (des []string) {
	des = make([]string, 0, len(arr))
	enc := mahonia.NewEncoder("gbk")

	for _, v := range arr {
		des = append(des, enc.ConvertString(v))
	}

	return
}

// Utf8StrToGBK utf-8 字符串转 gbk 数组
func Utf8StrToGBK(s string) string {
	enc := mahonia.NewEncoder("gbk")
	return enc.ConvertString(s)
}

func AnyToStr(i any) string {
	switch v := i.(type) {
	case string:
		return v
	case int:
		return strconv.FormatInt(int64(v), 10)
	case int32:
		return strconv.FormatInt(int64(v), 10)
	case int64:
		return strconv.FormatInt(v, 10)
	case float32:
		return strconv.FormatFloat(float64(v), 'f', -1, 32)
	case float64:
		return strconv.FormatFloat(v, 'f', -1, 64)
	case bool:
		return strconv.FormatBool(v)
	}
	return ""
}

func StructToMapBf(a any) (m map[string]any, err error) {
	if marshalContent, err := json.Marshal(a); err != nil {
		return nil, err
	} else {
		d := json.NewDecoder(bytes.NewReader(marshalContent))
		d.UseNumber() // 设置将float64转为一个number
		if err := d.Decode(&m); err != nil {
			return nil, err
		} else {
			for k, v := range m {
				m[k] = v
			}
		}
	}
	return
}

func StructToStrMap(a any) (m map[string]string, err error) {
	tmpM, err := StructToMap(a)
	if err != nil {
		return nil, err
	}
	m = make(map[string]string, 0)
	for k, v := range tmpM {
		m[k] = AnyToStr(v)
	}
	return
}
